using System.Globalization;
using Amazon.S3;
using GamFi.Admin.API.Application;
using GamFi.Admin.API.Domain.Entities;
using GamFi.Admin.API.Infrastructure;
using GamFi.Admin.API.Persistence;
using GamFi.Admin.API.Persistence.Context;
using GamFi.Admin.API.S3;
using GamFi.Admin.API.WEB.Middlewares;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Localization.Routing;
using Microsoft.EntityFrameworkCore;
using MongoDB.Driver;
using Migrator = GamFi.Admin.API.Persistence.Context.Migrator;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddDbContext<EfContext>(options =>
    options.UseNpgsql(builder.Configuration.GetConnectionString("PostgreSQL")));

builder.Services.AddSingleton<IMongoClient>(sp =>
{
    var connectionString = builder.Configuration.GetConnectionString("MongoDB");
    return new MongoClient(connectionString);
});

builder.Services.AddScoped<IMongoDatabase>(sp =>
{
    var client = sp.GetRequiredService<IMongoClient>();
    var mongoUrl = new MongoUrl(builder.Configuration.GetConnectionString("MongoDB"));
    var mongoDbDatabaseName = mongoUrl.DatabaseName;
    return client.GetDatabase(mongoDbDatabaseName);
});

builder.Services.AddIdentity<User, Role>(options =>
    {
        options.SignIn.RequireConfirmedAccount = true;
        options.Password.RequireLowercase = false;
        options.Password.RequireUppercase = false;
        options.Password.RequireNonAlphanumeric = false;
        options.Password.RequireDigit = false;
        options.User.RequireUniqueEmail = true;
        options.SignIn.RequireConfirmedEmail = true;
    })
    .AddDefaultTokenProviders()
    .AddEntityFrameworkStores<EfContext>();

builder.Services.ConfigureApplicationCookie(options => { options.Cookie.SameSite = SameSiteMode.None; });

builder.Services.AddInfrastructure(builder.Configuration);
builder.Services.AddPersistenceLayer();
builder.Services.AddApplicationLayer(builder.Configuration);
builder.Services.AddS3Storage(builder.Configuration.GetSection("AWS").Get<S3Options>()!);

builder.Services.AddAuthorization();
builder.Services.AddAuthentication().AddCookie(cookie => cookie.Cookie.SameSite = SameSiteMode.None);
builder.Services.AddCors(x =>
{
    x.AddPolicy("AllowAll", opt =>
    {
        opt.WithOrigins("http://localhost:3000");
        opt.AllowCredentials();
        opt.AllowAnyHeader();
        opt.AllowAnyMethod();
    });
});

builder.Services.AddControllers()
    .AddViewLocalization()
    .AddDataAnnotationsLocalization();
builder.Services.AddSignalR();
builder.Services.AddDefaultAWSOptions(builder.Configuration.GetAWSOptions());
builder.Services.AddAWSService<IAmazonS3>();


var app = builder.Build();

using var scope = app.Services.CreateScope();
var migrator = scope.ServiceProvider.GetRequiredService<Migrator>();
await migrator.MigrateAsync(new CancellationToken());

app.UseMiddleware<ExceptionHandlingMiddleware>();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}
else
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseCors("AllowAll");
app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

var supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("ru-RU") };
var localizationOptions = new RequestLocalizationOptions
{
    ApplyCurrentCultureToResponseHeaders = true,
    DefaultRequestCulture = new RequestCulture("en-US"),
    SupportedCultures = supportedCultures,
    SupportedUICultures = supportedCultures,
    RequestCultureProviders = new IRequestCultureProvider[]
    {
        new RouteDataRequestCultureProvider(),
        new CookieRequestCultureProvider()
    }
};

app.UseRequestLocalization(localizationOptions);

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();